#include "GameActions.h"
#include "Constants.h"
#include <EventManager.h>
#include "GameEventData.h"

// --------------------------------------------------
//  Level info action
// --------------------------------------------------
void LevelInfoAction::start() {
	setActive(true);
	m_LevelInfo->setActive(true);
	m_LevelInfo->setCounter(m_Core->getLevel());
	gEngine->getAudioManager().play("NextLevel",50,false);	
	m_LevelTimer = 0.0f;		
}

void LevelInfoAction::stop() {
	setActive(false);
	m_LevelInfo->setActive(false);
}

void LevelInfoAction::update(float elapsed) {
	m_LevelTimer += elapsed;
	float a = 1.0f - m_LevelTimer / LEVEL_INFO_TTL;
	m_LevelInfo->setColor(ds::Color(0.9f,0.9f,0.9f,a));
	float scale = 2.0f + m_LevelTimer/LEVEL_INFO_TTL * 2.0f;
	m_LevelInfo->setScale(ds::Vec2(scale,scale));
	float x = 430.0f - m_LevelTimer/LEVEL_INFO_TTL * 2.0f * 86.0f;
	float y = 348.0f - m_LevelTimer/LEVEL_INFO_TTL * 2.0f * 65.0f;
	m_LevelInfo->setPos(ds::Vec2(x,y));
	if ( m_LevelTimer > LEVEL_INFO_TTL ) {
		stop();
		FIRE_EMPTY_EVENT(EVN_START_WAVE);
	}
}

// --------------------------------------------------
//  Powerup Info action
// --------------------------------------------------
void PowerupInfoAction::start() {
	setActive(true);	
	m_Sprites->setVisible(m_SpriteHandle,true);
	//gEngine->getAudioManager().play("NextLevel",50,false);	
	m_InfoTimer = 0.0f;		
}

void PowerupInfoAction::stop() {
	setActive(false);
	m_Sprites->setVisible(m_SpriteHandle,false);
	m_InfoTimer = 0.0f;		
}

void PowerupInfoAction::update(float elapsed) {
	m_InfoTimer += elapsed;
	float a = 1.0f - m_InfoTimer / POWERUP_INFO_TTL;	
	m_Sprites->setColor(m_SpriteHandle,ds::Color(0.9f,0.9f,0.9f,a));
	float scale = 1.0f + m_InfoTimer/LEVEL_INFO_TTL;// * 2.0f;
	m_Sprites->setScale(m_SpriteHandle,ds::Vec2(scale,scale));
	float x = m_StartX- m_InfoTimer/POWERUP_INFO_TTL * m_TextureRect.width()* 0.5f;// * 86.0f;
	float y = m_StartY - m_InfoTimer/POWERUP_INFO_TTL *  m_TextureRect.height() * 0.5f;// * 65.0f;
	m_Sprites->setPosition(m_SpriteHandle,ds::Vec2(x,y));	
	if ( m_InfoTimer > POWERUP_INFO_TTL ) {
		stop();
	}
}

// --------------------------------------------------
//  Clear action
// --------------------------------------------------
void ClearAction::start() {
	m_Core->enemies()->setActive(false);
	//m_Core->meteoroids().setActive(false);
	m_Core->meteoroids().clear();
	m_Core->bullets().clear();
	m_Core->swimmer().setActive(false);
	m_Core->player().setBlocked(true);
	m_Core->floatingParticles().clear();		
}

// --------------------------------------------------
//  Shoot action
// --------------------------------------------------
void ShootAction::start() {
	m_Core->bullets().clear();
	m_Timer = 1000.0f;
}

void ShootAction::update(float elapsed) {
	for ( int i = 0; i < 8; ++i ) {
		// update bullets
		m_Core->bullets().update(elapsed);
		gEngine->getCollisionDetector().update();
	}
	ds::Vec2 p = m_Core->player().getPosition();
	float x = p.x + 40.0f;
	float y = p.y + 12.0f;
	m_Timer += elapsed;
	if ( m_Timer > SHOT_DELAY ) {
		m_Timer = 0.0f;			
		m_Core->bullets().start(ds::Vec2(x,y));				
	}
}

// --------------------------------------------------
//  Set targets action
// --------------------------------------------------
void SetTargetsAction::update(float elapsed) {
	ds::Vec2 p = m_Core->player().getPosition();
	float x = p.x + 40.0f;
	float y = p.y + 12.0f;
	m_Core->floatingParticles().setTargetPosition(ds::Vec2(x,y));
	m_Core->swimmer().setTarget(ds::Vec2(x,y));
	// pick up particles	
	int ret = m_Core->floatingParticles().pickupParticles(m_Core->player().getPosition(),ds::Vec2(115,70));
	if ( ret > 0 ) {
		gEngine->getAudioManager().play("Pickup",30,false);
		m_Core->hud().addScore(10*ret);
		m_PickupCounter += ret;
		m_Core->hud().incCredits(ret);
		if ( m_PickupCounter > 10 ) {
			m_PickupCounter -= 10;
			FIRE_EMPTY_EVENT(EVN_RELEASE_POWERUP);
		}
	}		
}

// --------------------------------------------------
//  Update enemies action
// --------------------------------------------------
void UpdateEnemiesAction::start() {
	m_Core->enemies()->setActive(true);
	setActive(true);
}

void UpdateEnemiesAction::stop() {
	m_Core->enemies()->setActive(false);
	setActive(false);
}

void UpdateEnemiesAction::update(float elapsed) {
	m_Core->asteroids().update(elapsed);
	m_Core->meteoroids().update(elapsed);
	m_Core->floatingParticles().update(elapsed);
}

// -------------------------------------------------
//  Blitz action
// -------------------------------------------------
void BlitzAction::start() {
	m_FadeTimer = 0.0f;
	setActive(true);
}

void BlitzAction::stop() {
	setActive(false);
}

void BlitzAction::update(float elapsed) {
	ds::Shader& shader = gEngine->getResourceManager().getShader(m_ShaderHandle);
	m_FadeTimer += elapsed;
	if ( m_FadeTimer > 0.5f ) {		
		m_FadeTimer = 0.0f;
		stop();
	}
	shader.setFloat("timer",m_FadeTimer);
}

// -------------------------------------------------
//
//  BlitzAction
//
// -------------------------------------------------
void FlashAction::start() {
	m_Timer = 0.0f;
	setActive(true);
}

void FlashAction::stop() {
	ds::Shader& shader = gEngine->getResourceManager().getShader(m_ShaderHandle);
	shader.setFloat("flashTimer",0.0f);
	setActive(false);
}

void FlashAction::update(float elapsed) {
	ds::Shader& shader = gEngine->getResourceManager().getShader(m_ShaderHandle);
	m_Timer += elapsed * 10.0f;
	shader.setFloat("flashTimer",m_Timer);
}

// -------------------------------------------------
//
//  GrayFadeAction
//
// -------------------------------------------------
void GrayFadeAction::start() {
	m_FadeTimer = 0.0f;
	setActive(true);
}

void GrayFadeAction::stop() {
	setActive(false);
}

void GrayFadeAction::update(float elapsed) {
	ds::Shader& shader = gEngine->getResourceManager().getShader(m_ShaderHandle);
	m_FadeTimer += elapsed;
	if ( m_FadeTimer > FADING_TTL ) {		
		m_FadeTimer = FADING_TTL;
	}
	shader.setFloat("timer",m_FadeTimer);
}

// -------------------------------------------------
//
//  BackgroundAction
//
// -------------------------------------------------
void BackgroundAction::start() {
	m_Timer = 0.0f;
	setActive(true);
}

void BackgroundAction::stop() {
	setActive(false);
}

void BackgroundAction::update(float elapsed) {
	m_Timer += elapsed;
	ds::Shader& shader = gEngine->getResourceManager().getShader(m_ShaderHandle);
	ds::Vec3 position = ds::Vec3(
		cos(m_Timer / starsParallaxPeriod),
		sin(m_Timer / starsParallaxPeriod),
		0.0f) *
		starsParallaxAmplitude;		
	shader.setVec3("position",position);
	shader.setFloat("timer",m_Timer);
}
// -------------------------------------------------
//
//  SwimmerAction
//
// -------------------------------------------------
void SwimmerAction::start() {
	m_Core->swimmer().setActive(true);
	setActive(true);
	m_SpawnTimer = 0.0f;
}

void SwimmerAction::stop() {
	m_Core->swimmer().setActive(false);
	m_Core->swimmer().clear();
	setActive(false);
}

void SwimmerAction::update(float elapsed) {
	m_SpawnTimer += elapsed;
	if ( m_SpawnTimer > m_Spawning ) {
		m_SpawnTimer = 0.0f;
		m_Core->swimmer().create(m_Count);
	}
	m_Core->swimmer().update(elapsed);	
}